﻿using Casamiel.API.Infrastructure.ActionResults;
using Casamiel.API.Infrastructure.Exceptions;
using Casamiel.Application;
using Casamiel.Domain;
using FluentValidation;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NLog;
using System;
using System.Net;

namespace Casamiel.API.Infrastructure.Filters
{
    /// <summary>
    /// Http global exception filter.
    /// </summary>
    public class HttpGlobalExceptionFilter : IExceptionFilter, IActionFilter
    {
        private readonly IWebHostEnvironment env;
        private readonly ILogger<HttpGlobalExceptionFilter> logger;
        private readonly NLog.ILogger _logger = LogManager.GetLogger("SystemErrorInfo");
        private readonly IErrorLogService _errorLog;
        /// <summary>
        /// Initializes a new instance of the
        /// <see cref="T:Casamiel.API.Infrastructure.Filters.HttpGlobalExceptionFilter"/> class.
        /// </summary>
        /// <param name="env">Env.</param>
        /// <param name="logger">Logger.</param>
        /// <param name="errorLog">Error log.</param>
        public HttpGlobalExceptionFilter(IWebHostEnvironment env, ILogger<HttpGlobalExceptionFilter> logger, IErrorLogService errorLog)
        {
            this.env = env;
            this.logger = logger;
            this._errorLog = errorLog;
        }
        /// <summary>
        /// Ons the action executed.
        /// </summary>
        /// <param name="context">Context.</param>
        public void OnActionExecuted(ActionExecutedContext context)
        {

        }
        /// <summary>
        /// Ons the action executing.
        /// </summary>
        /// <param name="context">Context.</param>
        public void OnActionExecuting(ActionExecutingContext context)
        {
            context.HttpContext.Items["_content_"] = $"{context.ActionDescriptor.DisplayName}:{ JsonConvert.SerializeObject(context.ActionArguments)}";
        }

        /// <summary>
        /// Ons the exception.
        /// </summary>
        /// <param name="context">Context.</param>
        public void OnException(ExceptionContext context)
        {
            _logger.Error($"GlobalExcption:{context.Exception.Message}");
            _logger.Error($"GlobalExcption:{context.Exception.StackTrace}");
            _logger.Error(context.Exception, "GlobalExcption");
            this.logger.LogError(new EventId(context.Exception.HResult),
             context.Exception, context.Exception.Message);

            if (context.Exception.GetType() == typeof(CasamielDomainException)) {
                var problemDetails = new ValidationProblemDetails() {
                    Instance = context.HttpContext.Request.Path,
                    //Status = StatusCodes.Status400BadRequest,
                    Detail = "Please refer to the errors property for additional details."
                };
                var a = (CasamielDomainException)context.Exception;
                if (a.InnerException.GetType() == typeof(ValidationException)) {
                    var v = (ValidationException)a.InnerException;
                    var json1 = new {

                        code = 9999,
                        content = v.Message,
                        msg = string.Join(',', v.Errors)
                    };
                    try {
                        var entity = new ErrorLog {
                            Url = context.HttpContext.Request.Path,
                            Loginfo = context.HttpContext.Items["a"].ToString(),
                            OPTime = DateTime.Now,
                            StackTrace = context.Exception.StackTrace,
                            Type = 1
                        };
                       // _errorLog.Add<ICasaMielSession>(entity);
                        _logger.Error($"{JsonConvert.SerializeObject(json1)}");
                    } catch (System.Data.SqlClient.SqlException ex) {
                        _logger.Error($"{ex.StackTrace}");
                    }

                    context.Result = new JsonResult(new {
                        code = 9999,
                        msg = string.Join(',', v.Errors)
                    });
                    context.ExceptionHandled = true;
                    return;
                }

                problemDetails.Errors.Add("DomainValidations", new string[] { context.Exception.Message });
                _logger.Error($"{JsonConvert.SerializeObject(problemDetails)}");
                //context.Result = new BadRequestObjectResult(problemDetails);
                //context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                context.Result = new JsonResult(new {
                    code = 9999,
                    msg = "抱歉请重试"
                });
                context.ExceptionHandled = true;
                return;
            } else {
                try {
                    var entity = new ErrorLog {
                        Url = context.HttpContext.Request.Path,
                        Loginfo = context.HttpContext.Items["_content_"].ToString(),
                        OPTime = DateTime.Now,
                        StackTrace = context.Exception.StackTrace,
                        Type = 1
                    };
                    _errorLog.Add<ICasaMielSession>(entity);
                    _logger.Error($"{context.HttpContext.Items["_content_"].ToString()}");
                } catch (System.Data.SqlClient.SqlException ex) {
                    _logger.Error($"{ex.StackTrace}");
                }

                var json = new JsonErrorResponse {
                    code = 9999,
                    msg = "抱歉请重试"
                };
                if (env.EnvironmentName== "Development") {
                    json.DeveloperMessage = context.Exception;
                }

                context.Result = new JsonResult(json);
                 
            }
            context.ExceptionHandled = true;
        }
    }
}
